package hu.bme.aut.consulttime.server.entityservices;

import hu.bme.aut.consulttime.client.StudentService;
import hu.bme.aut.consulttime.entitydtos.UserDTO;
import hu.bme.aut.consulttime.server.entities.Student;
import jBCrypt.BCrypt;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.TypedQuery;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

public class StudentServiceImpl extends RemoteServiceServlet implements
		StudentService {
	private static final long serialVersionUID = -1128004193526225930L;

	private static final EntityManager entityManager() {
		return EntityManagerFactoryWrapper.get().createEntityManager();
	}

	public Boolean createStudent(UserDTO studentDTO) {
		EntityManager em = entityManager();
		try {
			em.getTransaction().begin();
			Student student = new Student();
			student.setUserName(studentDTO.getUserName());
			student.setEmail(studentDTO.getEmail());
			student.setEmailNotification(studentDTO.isEmailNotification());
			student.setFirstName(studentDTO.getFirstName());
			student.setLastName(studentDTO.getLastName());
			// Password hash
			String passwordHash = BCrypt.hashpw(studentDTO.getPassword(),
					BCrypt.gensalt());
			student.setPassword(passwordHash);
			em.persist(student);

			em.getTransaction().commit();
			return true;
		} finally {
			em.close();
		}
	}

	public Boolean updateStudentPassword(UserDTO studentDTO) {
		EntityManager em = entityManager();
		try {
			em.getTransaction().begin();
			Student student = em.find(Student.class, studentDTO.getUserId());

			// Password hash
			String passwordHash = BCrypt.hashpw(studentDTO.getPassword(),
					BCrypt.gensalt());

			if (student != null) {
				student.setPassword(passwordHash);
			}
			em.getTransaction().commit();
		} finally {
			em.close();
		}
		return true;
	}

	public Boolean deleteStudent(long id) {
		EntityManager em = entityManager();
		EntityTransaction tx = em.getTransaction();

		Student student = em.find(Student.class, id);
		if(student == null) {
			return false;
		}
		try {
			tx.begin();
			em.remove(student);
			tx.commit();
			return true;
		} catch (Throwable t) {
			t.printStackTrace();
			tx.rollback();
			return false;
		} finally {
			em.close();
		}
	}

	public List<UserDTO> retrieveStudents() {
		EntityManager em = entityManager();
		List<Student> students = null;

		try {
			TypedQuery<Student> query = em.createQuery(
					"select s from Student s", Student.class);
			students = query.getResultList();
		} finally {
			em.close();
		}

		List<UserDTO> userDTOs = new ArrayList<UserDTO>();
		for (Student tmp : students) {
			UserDTO student = new UserDTO();
			student.setUserId(tmp.getUserId());
			student.setUserName(tmp.getUserName());
			student.setEmail(tmp.getEmail());
			student.setEmailNotification(tmp.isEmailNotification());
			student.setFirstName(tmp.getFirstName());
			student.setLastName(tmp.getLastName());
			userDTOs.add(student);
		}

		return userDTOs;
	}
}
